跳到主要内容

资料结构体

HiEasyX 中,几乎所有控件(除了部分控件的部分方法不会)都会要求你在调用他们的函数的时候提供一个资料结构体(Profile)。这么说可能不太好理解,我们依然是以上次的测试代码为例:

HX::WindowProfile windowProfile;
while (true) {
...

HX::Window(HXStr("Hello World!"), windowProfile);

...
}

我们只关注创建虚拟窗口部分的代码。这里就可以看到 HX::WindowProfile 这个结构体了。这便是 HiEasyX 中的资料结构体:

信息

在 HiEasyX 中,你当通过 HX::Window 创建虚拟窗口再创建控件。当然,你可以创建多个窗口。

HX::WindowProfile 的结构体定义如下所示(当然你不需要记住这些定义,也不需要知道每个变量都是什么意思):

/**
* The profile for a window
*/
struct WindowProfile {
HXPoint Size = {300, 200};

// Set the size to a value less than 0(including 0) to put these setting unused
// The MinSize, if the user does not set a minimum value, it will be put as a value
// which can contain the folding icon of the window
HXPoint MinSize = {-1, -1};
HXPoint MaxSize = {-1, -1};

HXPoint LastSize = {0, 0};
HXPoint Position = {0, 0};
bool InDrag = false;
bool Folded = false;
bool InAllSize = false;
bool InRAllSize = false;
bool InWidthSize = false;
bool InRWidthSize = false;
bool InHeightSize = false;
bool InCursorStyling = false;

// Set this as false to disable the resizing of the window
bool Sizable = true;
// Set this as false to disable the moving of the window
bool Movable = true;

HXGInt DeltaX = 0;
HXGInt DeltaY = 0;
HXGInt OriginX = 0;
HXGInt OriginY = 0;
};

可以看到,这几乎包含一个窗口所需要的信息。包括其大小、位置、是否被在拉伸、是否在被拖拽、是否折叠等等。因此,资料结构体这个听上去比较高大上的东西,实际上就是控件的属性的集合。还不理解?更简单地说就是控件所需要的一切信息都会放在这个结构体中。如果你还是不理解,没关系,在后面的代码中你会逐渐对这个概念有一个深层次的理解。

在 HiEasyX 中资料结构体是用户读取、修改控件状态的唯一方法

危险

资料结构体的生命周期需要被严格把控,错误地规划资料结构体的生命周期会导致意料以外的错误结果。举个最简单的最容易犯的错误:

将资料结构体作为局部变量定义在渲染循环或其他局部空间中,例如:

while (true) {
HX::WindowProfile windowProfile;
...

HX::Window(HXStr("Hello World!"), windowProfile);

...
}

千万别这么做,这将会导致程序的功能发生异常,至于为什么会这样读者可以自行思考。简单来说,这么干相当于:每次绘制都要清空一次控件属性

现在再去看测试代码中是如何创建按钮的:

static HX::ButtonProfile buttonProfile;

...

if (HX::Button(HXStr("Hello Button"), buttonProfile)) {
++count;
}

是不是瞬间好理解了?资料结构体 HX::ButtonProfile 的定义如下:

/**
* The profile for a button
*/
struct ButtonProfile {
bool OnHover = false;
bool OnPressed = false;
// When the mouse button clicked down and didn't get up, OnHold
// will be true
bool OnHold = false;
HXPoint Size = {-1, -1};
};

这意味着,你可以通过修改 HX::ButtonProfile::Size 来实现自定义按钮的大小,就像这样:

static HX::ButtonProfile buttonProfile;
// 将按钮大小设置为 300, 300
buttonProfile.Size = { 300, 300 };

...

if (HX::Button(HXStr("Hello Button"), buttonProfile)) {
++count;
}

也可以通过 HX::ButtonProfile::OnPressed 判断按钮是否按下,就像这样:

if (HX::Button(HXStr("Hello Button"), buttonProfile)) {
++count;
}

if (buttonProfile.OnHover) {
printf("你的鼠标现在正在按钮上方");
}

需要注意的是,资料结构体应该在创建控件前修改,创建控件后读取请勿像这样使用资料结构体:

if (buttonProfile.OnHover) {
printf("你的鼠标现在正在按钮上方");
}

if (HX::Button(HXStr("Hello Button"), buttonProfile)) {
++count;
}

buttonProfile.Size = { 300, 300 };

这将会导致错误地结果。

当然,我知道尽管你已经了解了这些,可能依然对测试代码有很多疑问。HX::BeginSameLine 是什么?HX::Button 的返回值有什么意义?没关系,结下的文章就是要讨论这些。